package com.linkin.homepage.base.recycleview;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import androidx.recyclerview.widget.RecyclerView;

import com.linkin.homepage.base.util.ClickUtils;
import com.linkin.homepage.base.viewmapping.ViewMapUtil;

import java.util.ArrayList;
import java.util.List;

public abstract class BaseRCAdapter<VH extends BaseRCViewHolder> extends RecyclerView.Adapter<VH> implements View.OnClickListener {

    protected List mModelList;
    protected ViewGroup mViewParent = null;
    protected Context mContext;

    public BaseRCAdapter(Context context) {
        mContext = context;
        mModelList = new ArrayList<>();
//        ButterKnife.bind(this, new View(context));
    }

    protected abstract Class getHolderClz();

    protected abstract void onBindView(VH holder, int position);

    protected abstract void onClickView(VH holder, int position, View v);

    @Override
    public void onBindViewHolder(VH holder, int position) {
        try {
            onBindView(holder, position);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void setOnClickListener(View view) {
        view.setOnClickListener(this);
    }

    @Override
    public VH onCreateViewHolder(ViewGroup parent, int viewType) {
        if (parent != null) {
            mViewParent = parent;
        }
        return ViewMapUtil.mapForRecyclerView(mContext, (Class<VH>) getHolderClz(), parent);
    }

    @Override
    public int getItemCount() {
        return mModelList.size();
    }

    public boolean isEmpty() {
        return mModelList.isEmpty();
    }

    public boolean isNotEmpty() {
        return !mModelList.isEmpty();
    }

    public <T extends Object> T getLastItem() {
        int size = mModelList.size();
        return size > 0 ? getItem(size - 1) : null;
    }

    public <T extends Object> T getItem(int position) {
        if (position < 0 || position >= mModelList.size()) {
            return null;
        }
        return (T) mModelList.get(position);
    }

    public List getList() {
        return mModelList;
    }

    public void updateList(List list) {
        updateList(list, true);
    }

    public void updateList(List list, boolean refresh) {
        mModelList.clear();
        if (list != null && list.size() > 0) {
            mModelList.addAll(list);
        }
        if (refresh) {
            notifyDataSetChanged();
        }
    }

    public void addList(List list) {
        addList(list, true);
    }

    public void addList(List list, boolean refresh) {
        if (list != null && list.size() > 0) {
            int position = mModelList.size();
            mModelList.addAll(list);
            if (refresh) {
                notifyItemRangeInserted(position, list.size());
            }
        }
    }

    public void addList(int index, List list) {
        if (list != null && list.size() > 0) {
            index = Math.max(Math.min(index, mModelList.size()), 0);
            mModelList.addAll(index, list);
            notifyDataSetChanged();
        }
    }

    public void addListSpecific(List list) {
        if (list != null && list.size() > 0) {
            int position = mModelList.size();
            mModelList.addAll(list);
            notifyItemRangeInserted(position, list.size());
            if (position > 0) {
                notifyItemChanged(position - 1, "tag");
            }
        }
    }

    public void addItem(Object data) {
        addItem(data, true);
    }

    public void addItem(Object data, boolean refresh) {
        if (data != null) {
            int position = mModelList.size();
            mModelList.add(data);
            if (refresh) {
                notifyItemInserted(position);
            }
        }
    }

    public void addItem(int index, Object data) {
        addItem(index, data, true);
    }

    public void addItem(int index, Object data, boolean refresh) {
        if (data != null && index >= 0 && index <= mModelList.size()) {
            mModelList.add(index, data);
            if (refresh) {
                notifyDataSetChanged();
            }
        }
    }

    public void removeAt(int position) {
        removeAt(position, true);
    }

    public void removeAt(int position, boolean refresh) {
        if (position >= 0 && position < mModelList.size()) {
            mModelList.remove(position);
            if (refresh) {
                notifyDataSetChanged();
            }
        }
    }

    public int removeFrom(int position) {
        return removeFrom(position, true);
    }

    public int removeFrom(int position, boolean refresh) {
        int size = mModelList.size();
        if (position >= 0 && position < size) {
            int count = 0;
            for (int i = size - 1; i >= position; i--) {
                mModelList.remove(i);
                count++;
            }
            if (refresh) {
                notifyItemRangeRemoved(position, count);
            }
            return count;
        }
        return 0;
    }

    public void replaceItem(int position, Object data, boolean refresh) {
        if (data != null && position >= 0 && position < mModelList.size()) {
            mModelList.set(position, data);
            if (refresh) {
                notifyItemChanged(position, "tag");
            }
        }
    }

    public void clear() {
        clear(true);
    }

    public void clear(boolean refresh) {
        mModelList.clear();
        if (refresh) {
            notifyDataSetChanged();
        }
    }

    @Override
    public void onClick(View v) {
        if (ClickUtils.check(v) && v != null) {
            View rootView = getRootView(v);
            if (rootView != null) {
                Object object = rootView.getTag();
                if (object != null && object instanceof RecyclerView.ViewHolder) {
                    RecyclerView.ViewHolder viewHolder = (RecyclerView.ViewHolder) object;
                    if (rootView == viewHolder.itemView) {
                        int position = RecyclerViewUtils.getAdapterPosition((RecyclerView) mViewParent, viewHolder);
                        try {
                            onClickView((VH) viewHolder, position, v);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    private View getRootView(View view) {
        if (view.getWindowToken() != null) {
            if (mViewParent == null) {
                return null;
            }

            ViewParent parent = view.getParent();
            do {
                if (!(parent instanceof ViewGroup)) {
                    return null;
                }

                if (parent == mViewParent) {
                    return view;
                }

                view = (View) parent;
                parent = view.getParent();
            } while (true);
        }
        return view.getRootView();
    }
}
